# encoding: UTF-8

from time import sleep

#from PyQt4 import QtGui

from hft_api import HftApi
import os
import threading
import time

global signal 
signal = threading.Event()
#----------------------------------------------------------------------
def print_dict(d):
    """按照键值打印一个字典"""
    for key,value in d.items():
        print (key + ':' + str(value))
        
        
#----------------------------------------------------------------------
def simple_log(func):
    """简单装饰器用于输出函数名"""
    def wrapper(*args, **kw):
        print (str(func.__name__))
        return func(*args, **kw)
    return wrapper


########################################################################
class TestMdApi(HftApi):
    """测试用实例"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        super(TestMdApi, self).__init__()
        
    #----------------------------------------------------------------------
    @simple_log    
    def onFrontConnected(self):
        """服务器连接"""
        signal.set()
        pass

    #----------------------------------------------------------------------
    @simple_log    
    def onFrontDisconnected(self, n):
        """服务器断开"""
        print(n)
        
    #----------------------------------------------------------------------
    @simple_log    
    def onHeartBeatWarning(self, n):
        """心跳报警"""
        print (n)
    
    #----------------------------------------------------------------------
    @simple_log    
    def onRspError(self, error, n, last):
        """错误"""
        print_dict(error)
    
    @simple_log 
    #----------------------------------------------------------------------
    def onRspUserLogin(self, data, error, data2, n, last):
        """登陆回报"""
        print("  ---- [Rsp | onRspUserLogin]----  ")
        print_dict(data)
        print_dict(error)
        
    #----------------------------------------------------------------------
    @simple_log    
    def onRspUserLogout(self, data, error, n, last):
        """登出回报"""
        print("  ---- [Rsp | onRspUserLogout]----  ")
        print_dict(data)
        print_dict(error)
        
    #----------------------------------------------------------------------
    @simple_log
    def onRtnSTCMarketdata(self, data):
        """行情推送"""
        print("  ---- [RTN | onRtnSTCMarketdata]----  ")
        print_dict(data)
        print(1)
    
    @simple_log
    def onRtnDepthMarketData(self, data):
        """行情推送"""
        print("  ---- [RTN | onRtnDepthMarketData]----  ")
        print_dict(data)
        print(2)
    
    @simple_log
    def onRspOrderInsert(self, data, error, n, last):
        """报单失败响应"""
        print("  ---- [Rsp | onRspOrderInsert]----  ")
        print_dict(data)
        print_dict(error)
      
    @simple_log
    def onRspOrderAction(self, data, error, n, last):
        """撤单失败响应"""
        print("  ---- [Rsp | onRspOrderAction]----  ")
        print_dict(data)
        print_dict(error)

    @simple_log
    def onRspCalcBond(self, data, error, n, last):
        """债券计算器"""
        print("  ---- [Rsp | onRspCalcBond]----  ")
        print_dict(data)
        print_dict(error)

    @simple_log
    def onRtnRuleIndicator(self, data):
        """策略指标回报"""
        print("  ---- [RTN | onRtnRuleIndicator]----  ")
        print_dict(data)

    @simple_log
    def onRtnRuleProp(self, data):
        """策略参数回报"""
        print("  ---- [RTN | onRtnRuleProp]----  ")
        print_dict(data)

    @simple_log
    def onRspQryBond(self, data, error, n, last):
        """债券查询响应"""
        print("  ---- [Rsp | onRspQryBond]----  ")
        print_dict(data)
        print_dict(error)

    @simple_log
    def onRtnRuleOrder(self, data):
        """报单回报"""
        print("  ---- [RTN | OnRtnRuleOrder]----  ")
        print_dict(data)

    @simple_log
    def onRtnRuleTrade(self, data):
        """成交回报"""
        print("  ---- [RTN | OnRtnRuleTrade]----  ")
        print_dict(data)

    @simple_log
    def onRtnRulePosition(self, data):
        """持仓回报"""
        print("  ---- [RTN | OnRtnRulePosition]----  ")
        print_dict(data)
    
    @simple_log
    def onRtnRule(self, data):
        """策略回报"""
        print("  ---- [RTN | onRtnRule]----  ")
        print_dict(data)


    """
    主动API接口封装
    """
    #在C++环境中创建MdApi对象，传入参数是希望用来保存.con文件的地址
    #@param pszFlowPath 存贮订阅信息文件的目录，默认为当前目录
    #@return 创建出的UserApi
    #modify for udp marketdata
    def CreateApi(self):
        self.createUserApi()
            
    #删除接口对象本身
    #@remark 不再使用本接口对象时,调用该函数删除接口对象
    def Release(self):
        self.release()
        
    #初始化
    #@remark 初始化运行环境,只有调用后,接口才开始工作
    def Init(self):
        self.init()
        
    #等待接口线程结束运行
    #@return 线程退出代码 
    def Join(self):
        self.join()
        
    #退出
    def Exit(self):
        self.exit()
    
    #注册前置机网络地址
    #@param pszFrontAddress：前置机网络地址。
    #@remark 网络地址的格式为：“protocol://ipaddress:port”，如：”tcp://127.0.0.1:17001”。 
    #@remark “tcp”代表传输协议，“127.0.0.1”代表服务器地址。”17001”代表服务器端口号。
    def RegisterFront(self,ip_address):
        self.registerFront(ip_address)

    #登出请求
    def ReqUserLogout(self):
        self.reqUserLogout() 

    # 登录请求
    def ReqUserLogin(self, rule_id):
        print("ready to login")
        loginReq = {}  # 创建一个空字典
        loginReq['CustomerID'] = str(rule_id) # 参数作为字典键值的方式传入
        loginReq['Password'] = ''  # 键名和C++中的结构体成员名对应
        loginReq['MacAddress'] = ''
        loginReq['SubInstrumentMethod'] = '0'
        loginReq['IsRule'] = 1
        self.reqUserLogin(loginReq, 1) 
        print("  **** [Req | ReqUserLogin]****  ", loginReq)

    # 登录请求
    def SubMD(self, symbol, venue):
        print("订阅STC行情")
        subReq = {}
        subReq['InstrumentID'] = symbol
        subReq['ExchangeID'] = venue
        self.reqSubSTCMarketdata(subReq, 2)
        print("  **** [Req | SubMD]****  ", subReq)

        # subReq['InstrumentID'] = 'TF2009'
        # subReq['ExchangeID'] = 'CFFEX'
        # api.reqSubMarketData(subReq, 2)

    # 登录请求
    def SendOrder(self, symbol, ruleID, orderid):
        print("下单")
        orderReq = {}
        orderReq['AccountID'] = str(ruleID)
        orderReq['RuleID'] = ruleID
        orderReq['CommodityType'] = 'B'
        orderReq['InstrumentID'] = symbol
        orderReq['OrderPriceType'] = '2'
        orderReq['Direction'] = '0' #0 买入 1卖出
        orderReq['OffsetFlag'] = orderReq['Direction']
        orderReq['HedgeFlag'] = '1'
        orderReq['Price'] = 104.5162
        orderReq['Volume'] = 3000
        orderReq['YTM'] = 3.21
        orderReq['CustomerID'] = str(ruleID)
        orderReq['LegSettlType'] = 2 # 1/2/6/7(int)
        orderReq['OrderInnerID'] = orderid
        orderReq['Reserver1'] = '1'       #cross_venues
        orderReq['Reserver2'] = '2' #venues_selectF
        orderReq['Reserver3'] = ''       #venues_rdm_num
        orderReq['Reserver4'] = 'ODM_ODM,SOR_CTTJ' #self_select_venues
        print(orderReq)
        self.reqOrderInsert(orderReq, 3)
        print("  **** [Req | SendOrder]****  ", orderReq)

    # 债券计算请求
    def CalcBond(self, symbol):
        print("债券计算器")
        calReq1 = {}
        calReq1['BondID'] = symbol
        #define PRT_CP '2' ///净价
        #define PRT_DP '3' ///全价
        #define PRT_YTM '4' ///收益率
        calReq1['CalType'] = '4' 
        calReq1['YTM'] = 0.03425
        calReq1['DirtyPrice'] = 100.4321
        calReq1['CleanPrice'] = 100.1234
        calReq1['SettleType'] = 1
        calReq1['SettlementDate'] = '' 
        calReq1['TradeDate'] = '' 
        self.reqCalcBond(calReq1, 4)
        print("  **** [Req | CalcBond]****  ", calReq1)

    # 撤单请求
    def CancelOrder(self, orderid):
        print("撤单")
        cancelReq = {}
        cancelReq['OrderInnerID'] = orderid
        cancelReq['ActionFlag'] = '0'
        self.reqOrderAction(cancelReq, 5)
        print("  **** [Req | CancelOrder]****  ", cancelReq)

    # 设置策略指标
    def SetIndicator(self, ruleID, key, value, desc):
        print("设置策略指标")
        indReq = {}
        indReq['RuleID'] = ruleID
        indReq['IndicatorKey'] = key
        indReq['IndicatorValue'] = value
        indReq['CalcTime'] = time.strftime('%H:%M:%S',time.localtime(time.time()))
        indReq['Description'] = desc
        self.reqSetRuleIndicator(indReq, 6)
        print("  **** [Req | SetIndicator]****  ", indReq)

    # 设置策略参数
    def SetParam(self, ruleID, key, value, desc):
        print("设置策略参数")
        paraReq = {}
        paraReq['RuleID'] = ruleID
        paraReq['PropKey'] = key
        paraReq['PropValue'] = value
        paraReq['Description'] = desc
        self.reqUpdateRuleProp(paraReq, 7)
        print("  **** [Req | SetParam]****  ", paraReq)
    
    # 查询债券信息
    def QueryBond(self, symbol):
        print("查询债券")
        queryReq = {}
        queryReq['BondID'] = symbol
        # queryReq['ExchangeID'] = key
        self.reqQryBond(queryReq, 8)
        print("  **** [Req | QueryBond]****  ", queryReq)

#----------------------------------------------------------------------
def main():
    """
    test
    """
    #初始化
    api = TestMdApi()
    api.CreateApi()
    api.RegisterFront("tcp://47.100.198.101:32201")
    # api.RegisterFront("tcp://114.55.107.102:31022")
    api.Init()
    sleep(1)
    
    
    # 初始数据
    m_ruleid = 10002  #（登录用户）
    m_symbol = '200210.IB'  #（可交易的债券）
    m_venue = 'cdh'
    m_orderID = '001001000014'

    #登录
    api.ReqUserLogin(m_ruleid)
    sleep(1)

    # # 订阅STC行情/行情回报
    # api.SubMD(m_symbol, m_venue)
    api.SubMD(m_symbol, "CT")
    
    # # 下单/接收报单回报/接收成交
    api.SendOrder(m_symbol, m_ruleid, m_orderID)

    # # 债券计算器
    # api.CalcBond(m_symbol)

    # # 撤单/接收报单回报
    # api.CancelOrder(m_orderID)
    
    # # 设置策略指标/接收策略指标
    # api.SetIndicator(m_ruleid, "test", "value01", "test策略指标")

    # # 设置策略参数/接收策略参数
    # api.SetParam(m_ruleid, "volume", "1", "test parameter")

    # # 查询债券信息
    # api.QueryBond(m_symbol)
    # 发送信号报单（todo)


    sleep(300)



if __name__ == '__main__':
    main()
